﻿using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Modules.App;
using Modules.Entitys;
using Modules.Notify.Repositories;
using PmSoft;
using PmSoft.ApplicationContext;
using PmSoft.Exceptions;
using PmSoft.Jiguang;
using static Modules.Notify.NotifyConstants;

namespace Modules.Notify
{
    [UseDI(ServiceLifetime.Scoped)]
    public class WorkerNotifyService
    {
        private readonly WorkerNotifyRepository repository;
        private readonly IApplicationContext applicationContext;
        private readonly NotifyAttachmentService notifyAttachmentService;
        private readonly ILogger logger;
        private readonly IJiguangService jiguangService;
        private readonly AppDeviceService appDeviceService;

        public WorkerNotifyService(WorkerNotifyRepository repository, IApplicationContext applicationContext, NotifyAttachmentService notifyAttachmentService, ILogger<NotifyAttachmentService> logger, IJiguangService jiguangService, AppDeviceService appDeviceService)
        {
            this.repository = repository;
            this.applicationContext = applicationContext;
            this.notifyAttachmentService = notifyAttachmentService;
            this.logger = logger;
            this.jiguangService = jiguangService;
            this.appDeviceService = appDeviceService;
        }

        /// <summary>
        /// 创建工人通知
        /// </summary>
        /// <param name="entity"></param>
        /// <param name="attachmentIds"></param>
        public void CreateWorkerNotify(WorkerNotify entity, IEnumerable<string> attachmentIds)
        {
            entity.Creator = applicationContext.CurrentUser?.Name ?? string.Empty;
            entity.ReadedNum = 0;
            entity.CreateTime = DateTime.Now;
            entity.Id = Guid.NewGuid().ToString().Replace("-", "");
            if (attachmentIds.Count() == 0)
            {
                repository.Insert(entity);
                return;
            }
            try
            {
                applicationContext.Transaction.Begin();//开始事务
                repository.Insert(entity);
                foreach (var attachmentId in attachmentIds)
                {
                    notifyAttachmentService.CreateNotifyAttachment(new NotifyAttachment()
                    {
                        AttachmentId = attachmentId,
                        NotifyId = entity.Id,
                        AttachmentType = NotifyConstants.通知类型.工人通知,
                    });
                }
                applicationContext.Transaction.Complete();//完成事务

                #region 推送消息到App

                List<string> alias = appDeviceService.GetDevicesByProjectId(entity.ProjectId).Select(a => a.Alias).ToList();
                jiguangService.AppointPush(new AppointPushModel()
                {
                    Title = JiguangConstants.Tips,
                    Message = entity.Title,
                    Extras = new Dictionary<string, object>() {
                        { "behavior", Behavior.PageJump },
                        { "route", Route.Home }
                    },
                    TargetAlias = alias
                });

                #endregion 推送消息到App
            }
            catch (Exception ex)
            {
                applicationContext.Transaction.Abort();//回滚事务
                logger.LogError(ex, $"创建工人通知失败");
                throw new BusinessException("创建工人通知失败");
            }
        }

        public void DeletWorkerNotifys(IEnumerable<string> ids)
        {
            foreach (string id in ids)
                DeleteWorkerNotify(id);
        }

        public void DeleteWorkerNotify(string id)
        {
            repository.DeleteByEntityId(id);
        }

        public WorkerNotify? GetWorkerNotify(string id)
        {
            return repository.Get(id);
        }

        public void UpdateWorkerNotify(WorkerNotify entity, IEnumerable<string> attachmentIds)
        {
            if (attachmentIds.Count() == 0)
            {
                repository.Update(entity);
                return;
            }
            try
            {
                applicationContext.Transaction.Begin();//开始事务
                entity.UpdateTime = DateTime.Now;
                repository.Update(entity);
                //更新关联表
                List<NotifyAttachment> allLinks = notifyAttachmentService.GetNotifyAttachmentsByNotifyId(entity.Id, 通知类型.工人通知).ToList();
                List<NotifyAttachment> delLinks = allLinks.Where(i => !attachmentIds.Contains(i.AttachmentId)).ToList();
                List<string> addLinks = attachmentIds.Where(i => !allLinks.Exists(a => a.AttachmentId == i)).ToList();
                //删除旧关联
                notifyAttachmentService.DeletNotifyAttachments(delLinks.Select(i => i.Id).ToList());
                //创建新关联
                foreach (var attachmentId in addLinks)
                {
                    notifyAttachmentService.CreateNotifyAttachment(new NotifyAttachment()
                    {
                        AttachmentId = attachmentId,
                        NotifyId = entity.Id,
                        AttachmentType = NotifyConstants.通知类型.工人通知,
                    });
                }
                applicationContext.Transaction.Complete();//完成事务

                #region 推送消息到App

                List<string> alias = appDeviceService.GetDevicesByProjectId(entity.ProjectId).Select(a => a.Alias).ToList();
                jiguangService.AppointPush(new AppointPushModel()
                {
                    Title = JiguangConstants.Tips,
                    Message = entity.Title,
                    Extras = new Dictionary<string, object>() {
                        { "behavior", Behavior.PageJump },
                        { "route", Route.Home }
                    },
                    TargetAlias = alias
                });

                #endregion 推送消息到App
            }
            catch (Exception ex)
            {
                applicationContext.Transaction.Abort();//回滚事务
                logger.LogError(ex, $"更新工人通知失败");
                throw new BusinessException("更新工人通知失败");
            }
        }

        /// <summary>
        /// 获取工人通知分页
        /// </summary>
        /// <param name="query"></param>
        /// <param name="pageIndex"></param>
        /// <param name="pageSize"></param>
        /// <returns></returns>
        public IPagedList<WorkerNotify> GetWorkerNotifysByPage(NotifyQuery query, int pageIndex, int pageSize)
        {
            return repository.GetWorkerNotifysByPage(query, pageIndex, pageSize);
        }

        /// <summary>
        /// 根据查询条件获取所有工人通知
        /// </summary>
        /// <param name="query"></param>
        /// <returns></returns>
        public IEnumerable<WorkerNotify> GetAllWorkerNotifysByQuery(NotifyQuery query)
        {
            return repository.GetAllWorkerNotifysByQuery(query);
        }

        /// <summary>
        /// 获取工人通知总数
        /// </summary>
        /// <param name="query"></param>
        /// <returns></returns>
        public int GetWorkerNotifyCount(NotifyQuery query)
        {
            return repository.GetWorkerNotifyCount(query);
        }

        /// <summary>
        /// 通过人员Id获取该人员所属项目的工人通知
        /// </summary>
        /// <param name="personId"></param>
        /// <returns></returns>
        public IEnumerable<WorkerNotify> GetAllWorkerNotifiesByPersonId(int personId)
        {
            return repository.GetAllWorkerNotifiesByPersonId(personId);
        }
    }
}